/*!  \file  GKManager.h
 *	  
 * 
 *   \details   details
 *   \author    Yordan Madzhunkov German Research School for Simulation Sciences GmbH
 *   \version   1.0
 *   \date      10/31/2013 06:56:03 PM
 *   \copyright GNU Public License.
 */
#pragma once

class GK;
class Lock;

#include "TaskID.h"

// GKManager is design to be used by TaskManager TaskManager calls GK manager
// each time, when a given task wants to store a GK matrix in main memory,
// that later will accessed by other tasks. The whole idea is to avoid
// new/delete operators, since they are quite expencive
//
//
// the const methods are the thread safe onces :) 
// including the workerFunction
// this will prevent spoling the thread safety by accident
class GKManager {
public:
	enum { nLocks = 256 };
	GKManager(const int nGK, const GK * nat_ );
	GKManager(const int nGK_, const int n_);
	void allocate();
	~GKManager();

	// find a free GK matrix and assign it for the given taskID
	// after this call is complete
	// each call of getGK with the same taskID will result in 
	// the same GK Matrix
	GK * obtainGK (const TaskID taskID);

	// returns the GK matrix assosiated with given taskID
	// if the given taskID does not own a GK matrix, 
	// the code will go into infity loop
	// the method is thread safe
	const GK * getGK    (const TaskID taskID) const ;
	// slighty slower version of getGK
	// but more safe
	const GK * getGK_safe    (const TaskID taskID) const;
	// releases the GK matrix
	// assumes that there will be NO calls to getGK
	// during the execution of release 
	void releaseGK(const TaskID taskID);

	void setNat(const GK * nat_) { nat = nat_; };
private:
	int getGKID  (const TaskID t) const { return t    % nGK;   };
	int getLockID(const int gkID) const { return gkID % nLocks; };
	void setUp   (GK & gk, int gkID) const;
 
	Lock     * locks     ; // array of 256 locks
	double   * repStorage; // array of 4 * n * nGK doubles
	GK       * reps      ; // array of nGK
	TaskID   * owner     ; // who owns the given GK maxtrix
	const GK * nat       ; // pointer to the root representaiton
	int        nGK       ; // number of GK matrices
	int        n         ; // dimention of the problem

};
